package com.ssm.dboss;

import java.math.BigDecimal;
import java.math.RoundingMode;

public class FixedCalculateBlastingWarehouseTest {

    public static void main(String[] args) {




        /*
         * 逐仓统一账户计算预估爆仓价/破产价
         * mm: 维持保证金率 = 调整系数/杠杆 （为0时算出来的是破产价）
         * 多仓：强平价格=开仓价格+（仓位价值*mm-仓位占用保证金）/(张数*合约面值)
         * 空仓：强平价格=开仓价格- ((仓位价值*mm-仓位占用保证金）/(张数*合约面值))
         * 开仓价格 = 持仓均价
         *
         */
        Position position = new Position();
        //持仓
        position.setTotalPosition(new BigDecimal("50982.000000000000000000"));
        //持仓均价 todo 不确定 15844.411472025742995025
        position.setAvgPosition(new BigDecimal("15842.891926971343680330"));
        //1买/2卖
        position.setDirection(DirectionEnum.D_BUY.getValue());
        //仓位保证金
        position.setPositionMargin(new BigDecimal("15572.541164840882446013"));
        //杠杆
        position.setLeverage(51);

        //调整系数
        BigDecimal adjustVal = new BigDecimal("0.750000000000000000");
        //面值
        BigDecimal instrumentValue = new BigDecimal("0.001000000000000000");
        //todo 不确定 最新价格
        BigDecimal lastPrice = new BigDecimal("15733.5");

        //仓位价值
        BigDecimal positionValue = instrumentValue.multiply(position.getTotalPosition()).multiply(lastPrice).setScale(Constants.DECIMAL_PRECISION, RoundingMode.DOWN);
        System.out.println("仓位价值(" + positionValue + ")=面值(" + instrumentValue + ") * 持仓(" + position.getTotalPosition() + ") * 最新价(" + lastPrice + ")");

        BigDecimal maintainMarginRate = adjustVal.divide(BigDecimal.valueOf(position.getLeverage()), Constants.DECIMAL_PRECISION, RoundingMode.DOWN);
        System.out.println("维持保证金率(接管价格):" + maintainMarginRate);

        BigDecimal val = (positionValue.multiply(maintainMarginRate).subtract(position.getPositionMargin()))
                .divide(position.getTotalPosition().multiply(instrumentValue), Constants.DECIMAL_PRECISION, RoundingMode.DOWN);

        //价格
        BigDecimal explosionPrice;
        if (position.getDirection() == DirectionEnum.D_BUY.getValue()) {
            explosionPrice = position.getAvgPosition().add(val);
            System.out.println("多仓：强平价格(" + explosionPrice + ")=开仓价格 (" + position.getAvgPosition() + ")+（仓位价值(" + positionValue + ")*维持保证金率(0)-仓位占用保证金(" + position.getPositionMargin() + ")）/(张数(" + position.getTotalPosition() + ")*合约面值(" + instrumentValue + "))");
        } else {
            explosionPrice = position.getAvgPosition().subtract(val);
            System.out.println("空仓：强平价格(" + explosionPrice + ")=开仓价格 (" + position.getAvgPosition() + ")-（仓位价值(" + positionValue + ")*维持保证金率(0)-仓位占用保证金(" + position.getPositionMargin() + ")）/(张数(" + position.getTotalPosition() + ")*合约面值(" + instrumentValue + "))");
        }
        // 15510.6
        System.out.println(explosionPrice);
    }

    static class Position {
        /**
         * @desc: 持仓量
         * @author: Admin
         */
        private BigDecimal totalPosition;

        /**
         * @desc: 持仓均价
         * @author: Admin
         */
        private BigDecimal avgPosition;

        /**
         * @desc: 持仓保证金
         * @author: Admin
         */
        private BigDecimal positionMargin;


        /**
         * @desc: 1：买；2：卖
         * @author: Admin
         */
        private Integer direction;

        /**
         * 杠杆倍数
         */
        private Integer leverage;

        public BigDecimal getTotalPosition() {
            return totalPosition;
        }

        public void setTotalPosition(BigDecimal totalPosition) {
            this.totalPosition = totalPosition;
        }

        public BigDecimal getAvgPosition() {
            return avgPosition;
        }

        public void setAvgPosition(BigDecimal avgPosition) {
            this.avgPosition = avgPosition;
        }

        public BigDecimal getPositionMargin() {
            return positionMargin;
        }

        public void setPositionMargin(BigDecimal positionMargin) {
            this.positionMargin = positionMargin;
        }

        public Integer getDirection() {
            return direction;
        }

        public void setDirection(Integer direction) {
            this.direction = direction;
        }

        public Integer getLeverage() {
            return leverage;
        }

        public void setLeverage(Integer leverage) {
            this.leverage = leverage;
        }
    }

    static class Constants {
        /**
         * BigDecimal小数位数
         */
        public final static int DECIMAL_PRECISION = 18;

    }

    /**
     * 买卖方向
     *
     * @author: shilf
     * @createTime: 2018年4月11日 下午4:28:24
     * @version: v1.0
     */
    enum DirectionEnum {
        //买
        D_BUY(1, "buy", "买"),
        //卖
        D_SELL(2, "sell", "卖");

        private int value;
        private String stringValue;
        private String cnName;

        DirectionEnum(int value, String stringValue, String cnName) {
            this.value = value;
            this.stringValue = stringValue;
            this.cnName = cnName;
        }

        public int getValue() {
            return value;
        }

        public String getStringValue() {
            return stringValue;
        }

        public String getCnName() {
            return cnName;
        }

        public static int getValue(String strname) {
            int val = -1;
            for (DirectionEnum em : DirectionEnum.values()) {
                if (em.stringValue.equalsIgnoreCase(strname)) {
                    val = em.value;
                    break;
                }
            }
            return val;
        }

        public static String getStringValue(int value) {
            for (DirectionEnum c : DirectionEnum.values()) {
                if (c.value == value) {
                    return c.stringValue;
                }
            }
            return value + "";
        }

        public static String getCnName(int value) {
            for (DirectionEnum c : DirectionEnum.values()) {
                if (c.value == value) {
                    return c.cnName;
                }
            }
            return value + "";
        }
    }

}
